//
//  ERField.m
//  metadata
//
//  Created by easy on 11-5-30.
//  Copyright 2011 zeasy@qq.com. All rights reserved.
//

#import "ERField.h"

#import "ERClassType.h"
@implementation ERField
//@synthesize entity;
@synthesize source;
@synthesize name;
@synthesize classType;
@synthesize size;
@synthesize alignment;
@synthesize offset;
#pragma mark init
-(id) initWithIvar:(Ivar) ivar{
	if (self = [super init]) {
		source = ivar;
		offset = ivar_getOffset(ivar);
	}
	return self;
}
#pragma mark property setter/getter
-(ERFieldEntity *) entity{
	if (!entity) {
		entity = [[ERFieldEntity entityWithIvar:self.source] retain];
	}
	return entity;
}
-(NSString *) name{
	return [self entity].name;
}
-(ERClassType *) classType{
	return [self entity].classType;
}
-(NSUInteger) size{
	return [self entity].classType.size;
}
-(NSUInteger) alignment{
	return [self entity].classType.alignment;
}
#pragma mark objc runtime at object_
-(id) valueAt:(id) object{
	return object_getIvar(object, self.source);
}
-(void) setValue:(id)value at:(id) object{
	if ([self.classType isObject]) {
		[object_getIvar(object, self.source) release];                  //old value release
		object_setIvar(object, self.source, [value retain]);    //new value retain
	}else {
		[self setPointerValue:(void *)value at:object];
	}
}
-(void *) pointerValueAt:(id) object{
	void *value = nil;
	object_getInstanceVariable(object, [self.name cStringUsingEncoding:ER_DEFAULT_ENCODING], &value);
	return value;
}
-(void) setPointerValue:(void *)value at:(id) object{
	object_setInstanceVariable(object, [self.name cStringUsingEncoding:ER_DEFAULT_ENCODING], value);
}
-(int) intValueAt:(id) object{
	return (int)[self pointerValueAt:object]; 
}
-(void) setIntValue:(int) value at:(id) object{ 
	[self setPointerValue:(void *)value at:object];
}
-(BOOL) boolValueAt:(id) object{
	return (BOOL)[self pointerValueAt:object];
}
-(void) setBoolValue:(BOOL) value at: (id) object{
	[self setPointerValue:(void *)value  at:object];
}
-(char) charValueAt:(id) object{
	return (char)[self pointerValueAt:object];
}
-(void) setCharValue:(char) value at: (id) object{
	[self setPointerValue:(void *)value at:object];
}
-(short) shortValueAt:(id) object{
	return (short)[self pointerValueAt:object];
}
-(void) setShortValue:(short) value at:(id) object{
	[self setPointerValue:(void *) value at:object];
}
-(float) floatValueAt:(id) object{
	void * v = [self pointerValueAt:object]; 
	float *f = &v;
	return *f;
}
-(void) setFloatValue:(float) value at:(id) object{
	float *f = &value;
	void **v = f;
	[self setPointerValue:*v at:object];
}
-(double) doubleValueAt:(id) object{
	void * v = [self pointerValueAt:object];
	double *d = &v;
	return *d;
}
-(void) setDoubleValue:(double) value at:(id) object{
	double *d = &value;
	void **v = d;
	[self setPointerValue:*v at:object];
}
-(long) longValueAt:(id) object{
	return (long)[self pointerValueAt:object];
}
-(void) setLongValue:(long) value at:(id) object{
	[self setPointerValue:(void *) value at:object];
}
-(void) dealloc{
	[entity release];
	[super dealloc];
}
@end


#pragma mark - 
@implementation ERFieldEntity
@synthesize name;
@synthesize classType;
-(id) initWithName:(NSString *) aName type:(ERClassType *) type{
	if (self = [super init]) {
		self.name = aName;			//set retain
		self.classType = type;		//set retain
	}
	return self;
}
+(id) entityWithName:(NSString *) aName type:(ERClassType *) type{
	return [[[ERFieldEntity alloc] initWithName:aName type:type] autorelease];
}
+(id) entityWithIvar:(Ivar) var{
	NSString *aName = ER_STRING_ALLOC(ivar_getName(var));
	NSString *aTypeString = ER_STRING_ALLOC(ivar_getTypeEncoding(var));
	ERClassType *cType = [[ERClassType alloc] initWithType:aTypeString];
	ERFieldEntity *entity = [[ERFieldEntity alloc] initWithName:aName type:cType];
	[aName release];
	[cType release];
	return [entity autorelease];
}

+(id) entityWithName:(NSString *) aName fromClass:(Class) clazz{
	return [ERFieldEntity entityWithName:aName fromClass:[ERClassType classType:clazz]];
}
+(id) entityWithName:(NSString *) aName fromERClass:(ERClass *) erClazz{
	return [ERFieldEntity entityWithName:aName type:[ERClassType erClassType:erClazz]];
}

+(id) intEntityWithName:(NSString *) aName{
	return [ERFieldEntity entityWithName:aName type:[ERClassType intClassType]];
}
+(id) charEntityWithName:(NSString *) aName{
	return [ERFieldEntity entityWithName:aName type:[ERClassType charClassType]];
}
+(id) boolEntityWithName:(NSString *) aName;{
	return [ERFieldEntity entityWithName:aName type:[ERClassType boolClassType]];
}
+(id) shortEntityWithName:(NSString *) aName{
	return [ERFieldEntity entityWithName:aName type:[ERClassType shortClassType]];
}
+(id) longEntityWithName:(NSString *) aName{
	return [ERFieldEntity entityWithName:aName type:[ERClassType longClassType]];
}
+(id) floatEntityWithName:(NSString *) aName{
	return [ERFieldEntity entityWithName:aName type:[ERClassType floatClassType]];
}
+(id) doubleEntityWithName:(NSString *) aName{
	return [ERFieldEntity entityWithName:aName type:[ERClassType doubleClassType]];
}
-(void) dealloc{
	[name release];
	[classType release];
	[super dealloc];
}
@end
